package com.glor.operation.common.utils;

import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.orm.hibernate3.SpringSessionContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by heylear.cai on 2016/2/18.
 */
public class RedisCacheHelper {

    public final static String CACHE_KEY_USER_ID = "CACHE_KEY_USER_ID";

    private static volatile RedisCacheHelper cacheHelper;

    private final static ReadWriteLock lock = new ReentrantReadWriteLock();

    private final static Lock readLock = lock.readLock();

    private final static Lock writeLock = lock.readLock();

    private Cache cache;

    private RedisCacheHelper(CacheManager cacheManager, String cacheName){
        this.cache = cacheManager.getCache(cacheName);
    }

    public static RedisCacheHelper getInstance(String cacheName){
        readLock.lock();
        try {
            if (cacheHelper == null){
                writeLock.lock();
                try {
                    CacheManager cacheManager = SpringContextHolder.getBean("cacheManager");
                    cacheHelper = new RedisCacheHelper(cacheManager, cacheName);
                } finally {
                    writeLock.unlock();
                }
            }
        } finally {
            readLock.unlock();
        }
        return cacheHelper;
    }

    public static RedisCacheHelper getDefaultInstance(){
        return getInstance("default");
    }

    public void setCache(String key, Object value){
        Assert.isInstanceOf(Serializable.class, value);
        cache.put(key, value);
    }

    public <T>  T getCache(String key, Class<T> clz){
        return cache.get(key, clz);
    }

    public void evictCache(String key){
        cache.evict(key);
    }

    public void evictUserCache(String cachePrefix){
        evictCache(cachePrefix + "_" + SpringContextHolder.getCurrentUserId());
    }


    public void setUserCache(String cachePrefix, Object value){
        setCache(cachePrefix + "_" + SpringContextHolder.getCurrentUserId(), value);
    }

    public <T> T getUserCache(String cachePrefix, Class<T> clz){
        return getCache(cachePrefix + "_" + SpringContextHolder.getCurrentUserId(), clz);
    }
    
}
